package com.chenl.interview.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.Header;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenl.interview.common.BaseResponse;
import com.chenl.interview.common.ErrorCode;
import com.chenl.interview.common.ResultUtils;
import com.chenl.interview.common.ThrowUtils;
import com.chenl.interview.constant.UserConstant;
import com.chenl.interview.exception.BusinessException;
import com.chenl.interview.model.dto.user.UserEditRequest;
import com.chenl.interview.model.dto.user.UserLoginRequest;
import com.chenl.interview.model.dto.user.UserQueryRequest;
import com.chenl.interview.model.dto.user.UserRegisterRequest;
import com.chenl.interview.model.entity.User;
import com.chenl.interview.model.vo.LoginUserVO;
import com.chenl.interview.model.vo.UserVO;
import com.chenl.interview.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import java.util.List;

import static com.chenl.interview.constant.UserConstant.USER_LOGIN_STATE;

/**
 * 用户
 */
@RestController
@RequestMapping("/user")
@Slf4j
@Api
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     * @param userRegisterRequest
     * @return
     */
    @PostMapping("/register")
    @ApiOperation(value = "用户注册")
    public BaseResponse<Long> register(@RequestBody UserRegisterRequest userRegisterRequest){
        //参数校验
        if (userRegisterRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Long id = userService.register(userAccount,userPassword,checkPassword);

        return ResultUtils.success(id);
    }

    /**
     * 用户登录
     * @param userLoginRequest
     * @param request
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "用户登录")
    public BaseResponse<LoginUserVO> login(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request){
        //参数校验
        if (userLoginRequest == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }

        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        String header = request.getHeader(Header.USER_AGENT.toString());

        if (StringUtils.isAnyBlank(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }

        // TODO: 2024/12/30 每次用户登录检测会员是否过期（这样不通过轮询，减少后端和数据库的压力）后期升级成MQ延迟队列
        LoginUserVO loginUserVO = userService.login(userAccount,userPassword,header);

        return ResultUtils.success(loginUserVO);
    }

    /**
     * 管理员分页查询用户
     * @param queryRequest
     * @return
     */
    @PostMapping("/list/page")
    @SaCheckRole("admin")
    @ApiOperation(value = "管理员分页查询用户")
    public BaseResponse<Page<User>> listUserByPage(@RequestBody UserQueryRequest queryRequest){
        //参数校验
        ThrowUtils.throwIf(queryRequest == null,new BusinessException(ErrorCode.PARAMS_ERROR));

        int pageSize = queryRequest.getPageSize();//页面大小
        int current = queryRequest.getCurrent();//页码
        if (pageSize < 0 || current < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Page<User> page =
                userService.page(new Page<>(current, pageSize), userService.getQueryWrapper(queryRequest));

        return ResultUtils.success(page);
    }

    /**
     * 根据id查询用户（仅管理员可用）
     * @param id
     * @return
     */
    @GetMapping("/get/{id}")
    @SaCheckRole("admin")
    @ApiOperation(value = "根据Id查询用户")
    public BaseResponse<User> getUserById(@PathVariable Long id){
        if (id == null || id < 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"非法参数");
        }

        User user = userService.getById(id);
        if (user == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"该id用户不存在");
        }
        //密码做模糊处理
        user.setUserPassword("***");
        return ResultUtils.success(user);
    }

    /**
     * 获取当前登录用户信息，用于给用户查看自己的信息
     * @return
     */
    @GetMapping("/get/login")
    @SaCheckLogin
    @ApiOperation(value = "获取当前登录用户信息")
    public BaseResponse<LoginUserVO> getLoginUser() {
        User user = (User)StpUtil.getSession().get(USER_LOGIN_STATE);
        LoginUserVO loginUserVO = BeanUtil.copyProperties(user, LoginUserVO.class);
        return ResultUtils.success(loginUserVO);
    }

    @PostMapping("/edit")
    @SaCheckLogin
    @ApiOperation(value = "用户修改个人信息")
    public BaseResponse<Boolean> editUser(@RequestBody UserEditRequest userEditRequest){
        //参数校验
        ThrowUtils.throwIf(userEditRequest == null,new BusinessException(ErrorCode.PARAMS_ERROR));

        User user = (User) StpUtil.getSession().get(USER_LOGIN_STATE);

        User newUser = BeanUtil.copyProperties(userEditRequest, User.class);
        newUser.setId(user.getId());

        boolean result = userService.updateById(newUser);

        if (!result){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }

        return ResultUtils.success(result);
    }

    @GetMapping("/get/vo/{id}")
    @SaCheckLogin
    @ApiOperation(value = "查看用户封装")
    public BaseResponse<UserVO> getUserVOById(@PathVariable Long id){
        //校验参数
        ThrowUtils.throwIf(id == null,new BusinessException(ErrorCode.PARAMS_ERROR));
        User user = userService.getById(id);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        //禁止查看管理员信息
        if (user.getUserRole().equals(UserConstant.ADMIN_ROLE)){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR);
        }
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);

        return ResultUtils.success(userVO);
    }

    //todo 删除用户信息（用户主动注销，逻辑删除）
    @PostMapping("/logout")
    @SaCheckLogin
    @ApiOperation(value = "用户注销")
    public BaseResponse<Boolean> logoutUser(){
        User user = (User)StpUtil.getSession().get(USER_LOGIN_STATE);

        //强制下线
        StpUtil.login(user.getId());
        StpUtil.getSession().clear();

        boolean result = userService.removeById(user.getId());
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }

        return ResultUtils.success(result);
    }

    //todo 删除用户（仅管理员，逻辑删除） 待测试
    @PostMapping("/delete/{id}")
    @SaCheckRole(value = UserConstant.ADMIN_ROLE)
    @ApiOperation(value = "删除用户，仅管理员")
    public BaseResponse<Boolean> deleteUser(@PathVariable Long id) {
        ThrowUtils.throwIf(id == null,new BusinessException(ErrorCode.PARAMS_ERROR));

        User user = userService.getById(id);
        ThrowUtils.throwIf(user == null,new BusinessException(ErrorCode.NOT_FOUND_ERROR));

        //强制下线
        StpUtil.logout(user.getId());
        StpUtil.getSessionByLoginId(user.getId()).clear();

        boolean result = userService.removeById(id);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }

        return ResultUtils.success(result);
    }

    //todo 封禁用户（仅管理员） 待测试
    @PostMapping("/ban/{id}")
    @SaCheckRole(value = UserConstant.ADMIN_ROLE)
    @ApiOperation(value = "封禁用户")
    public BaseResponse<Boolean> banUser(@PathVariable Long id){
        ThrowUtils.throwIf(id == null,new BusinessException(ErrorCode.PARAMS_ERROR));

        //强制下线
        StpUtil.logout(id);
        StpUtil.getSession().clear();

        User user = userService.getById(id);
        ThrowUtils.throwIf(user == null,new BusinessException(ErrorCode.NOT_FOUND_ERROR));
        user.setUserRole(UserConstant.BAN_ROLE);
        boolean result = userService.updateById(user);

        if (!result){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }

        return ResultUtils.success(result);
    }


    // TODO: 2025/1/2 待测试
    /**
     * 添加用户每日签到记录
     * @return 返回是否签到成功
     */
    @PostMapping("/add/sing_in")
    @SaCheckLogin
    @ApiOperation(value = "用户每日签到")
    public BaseResponse<Boolean> addUserSingIn(){
        User user = (User)StpUtil.getSession().get(USER_LOGIN_STATE);
        boolean result = userService.addUserSignIn(user.getId());
        if (!result){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success(result);
    }

    //todo 获取用户签到记录
    @PostMapping("/get/sign_in/{year}")
    @SaCheckLogin
    @ApiOperation(value = "获取用户签到记录")
    // TODO: 2025/1/2 待测试
    public BaseResponse<List<Integer>> getUserSingIn(@PathVariable Integer year){
        User user = (User)StpUtil.getSession().get(USER_LOGIN_STATE);

        List<Integer> result = userService.getUserSingIn(user.getId(),year);
        return ResultUtils.success(result);
    }


}
